package io.gitee.zhangbinhub.admin.adminserver.conf

import de.codecentric.boot.admin.server.config.AdminServerProperties
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpMethod
import org.springframework.security.config.Customizer
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler
import org.springframework.security.web.csrf.CookieCsrfTokenRepository
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
import java.util.*

@Configuration
class AdminServerAutoConfiguration @Autowired
constructor(adminServerProperties: AdminServerProperties) {
    private val adminContextPath: String = adminServerProperties.contextPath

    /**
     * http 验证策略配置
     *
     * @param http http 安全验证对象
     * @throws Exception 异常
     */
    @Bean
    @Throws(Exception::class)
    fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
        val successHandler = SavedRequestAwareAuthenticationSuccessHandler()
        successHandler.setTargetUrlParameter("redirectTo")
        successHandler.setDefaultTargetUrl("$adminContextPath/")
        http.authorizeHttpRequests { authorize ->
            authorize.requestMatchers(
                PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/assets/**"),
                PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/instances"),
                PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/instances/**"),
                PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/login"),
                PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/error"),
                PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/webjars/**"),
                PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/notifications/**"),
                PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/proxy.stream")
            ).permitAll().anyRequest().authenticated()
        }.httpBasic(Customizer.withDefaults())
            .formLogin { it.loginPage("$adminContextPath/login").successHandler(successHandler) }
            .logout { it.logoutUrl("$adminContextPath/logout") }

        http.csrf { csrf ->
            csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .csrfTokenRequestHandler(CsrfTokenRequestAttributeHandler())
                .ignoringRequestMatchers(
                    PathPatternRequestMatcher.withDefaults()
                        .matcher(HttpMethod.POST, "$adminContextPath/instances"),
                    PathPatternRequestMatcher.withDefaults()
                        .matcher(HttpMethod.DELETE, "$adminContextPath/instances/*"),
                    PathPatternRequestMatcher.withDefaults().matcher("$adminContextPath/actuator/**")
                )
        }

        http.rememberMe { rememberMe ->
            rememberMe.key(UUID.randomUUID().toString()).tokenValiditySeconds(1209600)
        }

        return http.build()
    }
}